package com.jerry.shop.service.impl;

import com.github.pagehelper.PageHelper;
import com.jerry.shop.bean.Order;
import com.jerry.shop.bean.OrderDetail;
import com.jerry.shop.bean.Product;
import com.jerry.shop.converter.OrderConverter;
import com.jerry.shop.dto.ProductDto;
import com.jerry.shop.dto.OrderDto;
import com.jerry.shop.enums.OrderStatusEnum;
import com.jerry.shop.enums.PayStatusEnum;
import com.jerry.shop.enums.ResultEnum;
import com.jerry.shop.exception.SellException;
import com.jerry.shop.mapper.OrderDetailMapper;
import com.jerry.shop.mapper.OrderMapper;
import com.jerry.shop.service.OrderService;
import com.jerry.shop.service.PayService;
import com.jerry.shop.service.ProductService;
import com.jerry.shop.utils.KeyUtil;
import com.jerry.shop.websocket.WebSocket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    ProductService productService;
    @Autowired
    private PayService payService;
//    @Autowired
//    private PushMessageService pushMessageService;
    @Autowired
    private WebSocket webSocket;

    public List<OrderDto> orderList2orderDtoList(List<Order> orderList) {
        //orderList转化为orderDtoList
        List<OrderDto> orderDtoList = OrderConverter.convert(orderList);
        //循环遍历orderDtoList, 为orderDtoList中增加商品
        for (OrderDto orderDto : orderDtoList) {
            List<OrderDetail> orderDetailList = orderDetailMapper.getOrderDetailListByOrderId(orderDto.getId());
            orderDto.setOrderDetailList(orderDetailList);
        }
        return orderDtoList;
    }

    @Override
    public List<OrderDto> findList() {

        //获取订单列表
        List<Order> orderList = orderMapper.getOrderList();
        List<OrderDto> orderDtoList = orderList2orderDtoList(orderList);

        return orderDtoList;
    }

    @Override
    public List<OrderDto> findList(String buyerId) {

        //根据购买者id, 获取订单列表
        List<Order> orderList = orderMapper.getOrderListByBuyerId(buyerId);
        List<OrderDto> orderDtoList = orderList2orderDtoList(orderList);

        return orderDtoList;
    }

    @Override
    public List<OrderDto> findListByPage(Integer page, Integer pageSize){
        // 开始分页,  *****只用加入这一行，就实现了分页*****
        PageHelper.startPage(page, pageSize);
        return findList();
    }

    @Override
    public List<OrderDto> findListByPage(String buyerId, Integer page, Integer pageSize){
        // 开始分页,  *****只用加入这一行，就实现了分页*****
        PageHelper.startPage(page, pageSize);
        return findList(buyerId);
    }

    @Override
    @Transactional    //事务
    public OrderDto create(OrderDto orderDto) {

        String orderId = KeyUtil.genUniqueKey();   //订单id
        BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO);

        //1. 遍历订单中的商品，计算商品总价
        for (OrderDetail orderDetail: orderDto.getOrderDetailList()) {
            //获取商品信息
            Product product =  productService.findOne(orderDetail.getProductId());
            if (product == null) {
                throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
            }

            //2. 计算订单总价
            orderAmount = product.getPrice()
                    .multiply(new BigDecimal(orderDetail.getProductQuantity()))
                    .add(orderAmount);

            //3. 订单中的每个商品入库
            orderDetail.setId(KeyUtil.genUniqueKey());   //订单详情id
            orderDetail.setOrderId(orderId);
            orderDetail.setProductId(product.getId());
            orderDetail.setProductName(product.getName());
            orderDetail.setProductPrice(product.getPrice());
            orderDetail.setProductIcon(product.getIcon());
            orderDetailMapper.insertOrderDetail(orderDetail);
        }

        //4. 写入订单数据库
        Order order = new Order();
        //orderDto属性赋值给order
        BeanUtils.copyProperties(orderDto, order);
        order.setId(orderId);
        order.setAmount(orderAmount);
        order.setStatus(OrderStatusEnum.NEW.getCode());
        order.setPayStatus(PayStatusEnum.WAIT.getCode());
        orderMapper.insertOrder(order);

        //5. 扣库存(使用lamda表达式)
        List<ProductDto> productDtoList = orderDto.getOrderDetailList().stream().map(e ->
                new ProductDto(e.getProductId(), e.getProductQuantity())
        ).collect(Collectors.toList());
        productService.decreaseStock(productDtoList);

        //发送websocket消息
        webSocket.sendMessage(order.getId());

        //order属性值赋值给orderDto
        BeanUtils.copyProperties(order, orderDto);

        return orderDto;
    }

    @Override
    public OrderDto findOne(String orderId) {

        //根据订单id，获取订单
        Order order = orderMapper.getOrderById(orderId);
        if (order == null) {
            throw new SellException(ResultEnum.ORDER_NOT_EXIST);
        }
        //根据订单id，获取下订单时的商品列表
        List<OrderDetail> orderDetailList = orderDetailMapper.getOrderDetailListByOrderId(orderId);
        if (CollectionUtils.isEmpty(orderDetailList)) {
            throw new SellException(ResultEnum.ORDERDETAIL_NOT_EXIST);
        }

        OrderDto orderDto = new OrderDto();
        //order属性赋值给orderDto
        BeanUtils.copyProperties(order, orderDto);
        orderDto.setOrderDetailList(orderDetailList);

        return orderDto;
    }

    @Override
    public OrderDto findOne(String buyerId, String orderId) {
        return checkOrderOwner(buyerId, orderId);
    }

    @Override
    @Transactional
    public OrderDto cancel(OrderDto orderDto) {
        //判断订单状态
        if (!orderDto.getStatus().equals(OrderStatusEnum.NEW.getCode())) {
            log.error("【取消订单】订单状态不正确, orderId={}, orderStatus={}", orderDto.getId(), orderDto.getStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }

        //修改订单状态
        orderDto.setStatus(OrderStatusEnum.CANCEL.getCode());
        Order order = new Order();
        //orderDto属性赋值给order
        BeanUtils.copyProperties(orderDto, order);

        //若订单状态更新成功
        if (orderMapper.updateOrder(order) == 1) {
            //返回库存
            if (CollectionUtils.isEmpty(orderDto.getOrderDetailList())) {
                log.error("【取消订单】订单中无商品, orderDto={}",orderDto);
                throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY);
            }
            //获取订单中所有商品
            List<ProductDto> productDtoList = orderDto.getOrderDetailList().stream()
                    .map(e -> new ProductDto(e.getProductId(), e.getProductQuantity()))
                    .collect(Collectors.toList());
            productService.increaseStock(productDtoList);

            //如果已支付, 需要退款
            if (orderDto.getPayStatus().equals(PayStatusEnum.SUCCESS.getCode())) {
                payService.refund(orderDto);
            }
        } else {
            log.error("【取消订单】更新失败, order={}", order);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }

        return orderDto;
    }

    @Override
    @Transactional
    public OrderDto cancel(String buyerId, String orderId) {
        OrderDto orderDTO = checkOrderOwner(buyerId, orderId);
        if (orderDTO == null) {
            log.error("【取消订单】查不到改订单, orderId={}", orderId);
            throw new SellException(ResultEnum.ORDER_NOT_EXIST);
        }

        return cancel(orderDTO);
    }

    @Override
    @Transactional
    public OrderDto finish(OrderDto orderDto) {
        //判断订单状态
        if (!orderDto.getStatus().equals(OrderStatusEnum.NEW.getCode())) {
            log.error("【完结订单】订单状态不正确, orderId={}, orderStatus={}",orderDto.getId(), orderDto.getStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }

        //修改订单状态
        orderDto.setStatus(OrderStatusEnum.FINISHED.getCode());
        Order order = new Order();
        //orderDto属性赋值给order
        BeanUtils.copyProperties(orderDto, order);

        if (orderMapper.updateOrder(order) == 1) {
            //推送微信模版消息
//            pushMessageService.orderStatus(orderDto);
        } else {
            log.error("【完结订单】更新失败, order={}", order);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }

        return orderDto;
    }

    @Override
    @Transactional
    public OrderDto paid(OrderDto orderDto) {
        //判断订单状态
        if (!orderDto.getStatus().equals(OrderStatusEnum.NEW.getCode())) {
            log.error("【订单支付完成】订单状态不正确, orderId={}, orderStatus={}", orderDto.getId(), orderDto.getStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }

        //判断支付状态
        if (!orderDto.getPayStatus().equals(PayStatusEnum.WAIT.getCode())) {
            log.error("【订单支付完成】订单支付状态不正确, orderDTO={}", orderDto);
            throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR);
        }

        //修改支付状态
        orderDto.setPayStatus(PayStatusEnum.SUCCESS.getCode());
        Order order = new Order();
        //orderDto属性赋值给order
        BeanUtils.copyProperties(orderDto, order);

        if (orderMapper.updateOrder(order) != 1) {
            log.error("【订单支付完成】更新失败, order={}", order);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }

        return orderDto;
    }

    private OrderDto checkOrderOwner(String buyerId, String orderId) {
        OrderDto orderDTO = findOne(orderId);
        if (orderDTO == null) {
            return null;
        }
        //判断是否是自己的订单
        if (!orderDTO.getBuyerId().equalsIgnoreCase(buyerId)) {
            log.error("【查询订单】订单的buyerId不一致. buyerId={}, orderDTO={}", buyerId, orderDTO);
            throw new SellException(ResultEnum.ORDER_OWNER_ERROR);
        }
        return orderDTO;
    }

}
